package com.cencat.route.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cencat.route.entity.Merchant;
import com.cencat.route.mapper.MerchantMapper;
import com.cencat.route.service.MerchantService;
import com.cencat.route.vo.MerchantQueryVO;
import com.cencat.route.vo.MerchantStatisticsVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

/**
 * 商户服务实现类
 * 
 * @author cencat
 * @since 2024-01-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MerchantServiceImpl extends ServiceImpl<MerchantMapper, Merchant> implements MerchantService {

    private final MerchantMapper merchantMapper;

    @Override
    public Page<Merchant> selectMerchantPage(Page<Merchant> page, MerchantQueryVO query) {
        return merchantMapper.selectMerchantPage(page, query);
    }

    @Override
    public List<Merchant> selectMerchantList(MerchantQueryVO query) {
        return merchantMapper.selectMerchantList(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateMerchantStatus(List<Long> ids, String status, Long updatedBy) {
        try {
            return merchantMapper.batchUpdateMerchantStatus(ids, status, updatedBy) > 0;
        } catch (Exception e) {
            log.error("批量更新商户状态失败: {}", e.getMessage(), e);
            throw new RuntimeException("批量更新商户状态失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateVerificationStatus(List<Long> ids, String verificationStatus, Long updatedBy) {
        try {
            return merchantMapper.batchUpdateVerificationStatus(ids, verificationStatus, updatedBy) > 0;
        } catch (Exception e) {
            log.error("批量更新商户认证状态失败: {}", e.getMessage(), e);
            throw new RuntimeException("批量更新商户认证状态失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateCreditScore(List<Long> ids, BigDecimal creditScore, Long updatedBy) {
        try {
            return merchantMapper.batchUpdateCreditScore(ids, creditScore, updatedBy) > 0;
        } catch (Exception e) {
            log.error("批量更新商户信用分数失败: {}", e.getMessage(), e);
            throw new RuntimeException("批量更新商户信用分数失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateCreditLevel(List<Long> ids, String creditLevel, Long updatedBy) {
        try {
            return merchantMapper.batchUpdateCreditLevel(ids, creditLevel, updatedBy) > 0;
        } catch (Exception e) {
            log.error("批量更新商户信用等级失败: {}", e.getMessage(), e);
            throw new RuntimeException("批量更新商户信用等级失败", e);
        }
    }

    @Override
    public MerchantStatisticsVO getMerchantStatistics() {
        try {
            return merchantMapper.getMerchantStatistics();
        } catch (Exception e) {
            log.error("获取商户统计信息失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取商户统计信息失败", e);
        }
    }

    @Override
    public String evaluateMerchantCredit(Long merchantId) {
        try {
            return merchantMapper.evaluateMerchantCredit(merchantId);
        } catch (Exception e) {
            log.error("评估商户信用失败: {}", e.getMessage(), e);
            throw new RuntimeException("评估商户信用失败", e);
        }
    }

    @Override
    public String analyzeMerchantBusiness(Long merchantId, String analysisType) {
        try {
            return merchantMapper.analyzeMerchantBusiness(merchantId, analysisType);
        } catch (Exception e) {
            log.error("分析商户业务失败: {}", e.getMessage(), e);
            throw new RuntimeException("分析商户业务失败", e);
        }
    }

    @Override
    public List<Merchant> getActiveMerchants(Integer limit) {
        try {
            return merchantMapper.getActiveMerchants(limit);
        } catch (Exception e) {
            log.error("获取活跃商户列表失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取活跃商户列表失败", e);
        }
    }

    @Override
    public List<Merchant> getVerifiedMerchants(Integer limit) {
        try {
            return merchantMapper.getVerifiedMerchants(limit);
        } catch (Exception e) {
            log.error("获取已认证商户列表失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取已认证商户列表失败", e);
        }
    }

    @Override
    public List<Merchant> getHighCreditMerchants(BigDecimal minCreditScore, Integer limit) {
        try {
            return merchantMapper.getHighCreditMerchants(minCreditScore, limit);
        } catch (Exception e) {
            log.error("获取高信用商户列表失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取高信用商户列表失败", e);
        }
    }

    @Override
    public List<Merchant> getNewRegisteredMerchants(Integer days, Integer limit) {
        try {
            return merchantMapper.getNewRegisteredMerchants(days, limit);
        } catch (Exception e) {
            log.error("获取新注册商户列表失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取新注册商户列表失败", e);
        }
    }

    @Override
    public List<Merchant> getPendingVerificationMerchants(Integer limit) {
        try {
            return merchantMapper.getPendingVerificationMerchants(limit);
        } catch (Exception e) {
            log.error("获取待认证商户列表失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取待认证商户列表失败", e);
        }
    }

    @Override
    public List<Merchant> getSuspendedMerchants(Integer limit) {
        try {
            return merchantMapper.getSuspendedMerchants(limit);
        } catch (Exception e) {
            log.error("获取暂停商户列表失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取暂停商户列表失败", e);
        }
    }

    @Override
    public boolean checkMerchantExists(Long id) {
        try {
            return merchantMapper.checkMerchantExists(id) > 0;
        } catch (Exception e) {
            log.error("检查商户是否存在失败: {}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean checkMerchantCodeExists(String merchantCode, Long excludeId) {
        try {
            return merchantMapper.checkMerchantCodeExists(merchantCode, excludeId) > 0;
        } catch (Exception e) {
            log.error("检查商户编码是否存在失败: {}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean checkMerchantNameExists(String merchantName, Long excludeId) {
        try {
            return merchantMapper.checkMerchantNameExists(merchantName, excludeId) > 0;
        } catch (Exception e) {
            log.error("检查商户名称是否存在失败: {}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean registerMerchant(Merchant merchant) {
        try {
            // 检查商户编码是否已存在
            if (checkMerchantCodeExists(merchant.getMerchantCode(), null)) {
                throw new RuntimeException("商户编码已存在");
            }
            
            // 检查商户名称是否已存在
            if (checkMerchantNameExists(merchant.getMerchantName(), null)) {
                throw new RuntimeException("商户名称已存在");
            }
            
            // 设置默认值
            merchant.setStatus("PENDING");
            merchant.setVerificationStatus("UNVERIFIED");
            merchant.setCreditScore(new BigDecimal("60.0"));
            merchant.setCreditLevel("C");
            
            return save(merchant);
        } catch (Exception e) {
            log.error("注册商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("注册商户失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean verifyMerchant(Long merchantId, String verificationStatus, String verificationNotes, Long verifiedBy) {
        try {
            return merchantMapper.verifyMerchant(merchantId, verificationStatus, verificationNotes, verifiedBy) > 0;
        } catch (Exception e) {
            log.error("认证商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("认证商户失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean activateMerchant(Long merchantId, Long activatedBy) {
        try {
            return merchantMapper.activateMerchant(merchantId, activatedBy) > 0;
        } catch (Exception e) {
            log.error("激活商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("激活商户失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean suspendMerchant(Long merchantId, String suspendReason, Long suspendedBy) {
        try {
            return merchantMapper.suspendMerchant(merchantId, suspendReason, suspendedBy) > 0;
        } catch (Exception e) {
            log.error("暂停商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("暂停商户失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean resumeMerchant(Long merchantId, Long resumedBy) {
        try {
            return merchantMapper.resumeMerchant(merchantId, resumedBy) > 0;
        } catch (Exception e) {
            log.error("恢复商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("恢复商户失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMerchantInfo(Long merchantId, String merchantName, String contactPerson, String contactPhone, String contactEmail, Long updatedBy) {
        try {
            return merchantMapper.updateMerchantInfo(merchantId, merchantName, contactPerson, contactPhone, contactEmail, updatedBy) > 0;
        } catch (Exception e) {
            log.error("更新商户信息失败: {}", e.getMessage(), e);
            throw new RuntimeException("更新商户信息失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMerchantAddress(Long merchantId, String businessAddress, String registeredAddress, Long updatedBy) {
        try {
            return merchantMapper.updateMerchantAddress(merchantId, businessAddress, registeredAddress, updatedBy) > 0;
        } catch (Exception e) {
            log.error("更新商户地址失败: {}", e.getMessage(), e);
            throw new RuntimeException("更新商户地址失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMerchantBusinessInfo(Long merchantId, String businessType, String businessScope, String businessLicense, Long updatedBy) {
        try {
            return merchantMapper.updateMerchantBusinessInfo(merchantId, businessType, businessScope, businessLicense, updatedBy) > 0;
        } catch (Exception e) {
            log.error("更新商户业务信息失败: {}", e.getMessage(), e);
            throw new RuntimeException("更新商户业务信息失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMerchantCreditInfo(Long merchantId, BigDecimal creditScore, String creditLevel, String creditNotes, Long updatedBy) {
        try {
            return merchantMapper.updateMerchantCreditInfo(merchantId, creditScore, creditLevel, creditNotes, updatedBy) > 0;
        } catch (Exception e) {
            log.error("更新商户信用信息失败: {}", e.getMessage(), e);
            throw new RuntimeException("更新商户信用信息失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMerchantServiceArea(Long merchantId, String serviceArea, String serviceRadius, Long updatedBy) {
        try {
            return merchantMapper.updateMerchantServiceArea(merchantId, serviceArea, serviceRadius, updatedBy) > 0;
        } catch (Exception e) {
            log.error("更新商户服务区域失败: {}", e.getMessage(), e);
            throw new RuntimeException("更新商户服务区域失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMerchantSettlement(Long merchantId, String settlementAccount, String settlementBank, String settlementPeriod, Long updatedBy) {
        try {
            return merchantMapper.updateMerchantSettlement(merchantId, settlementAccount, settlementBank, settlementPeriod, updatedBy) > 0;
        } catch (Exception e) {
            log.error("更新商户结算信息失败: {}", e.getMessage(), e);
            throw new RuntimeException("更新商户结算信息失败", e);
        }
    }

    @Override
    public String analyzeMerchantPerformance(Long merchantId, String startDate, String endDate) {
        try {
            return merchantMapper.analyzeMerchantPerformance(merchantId, startDate, endDate);
        } catch (Exception e) {
            log.error("分析商户性能失败: {}", e.getMessage(), e);
            throw new RuntimeException("分析商户性能失败", e);
        }
    }

    @Override
    public String generateMerchantReport(Long merchantId, String reportType) {
        try {
            return merchantMapper.generateMerchantReport(merchantId, reportType);
        } catch (Exception e) {
            log.error("生成商户报告失败: {}", e.getMessage(), e);
            throw new RuntimeException("生成商户报告失败", e);
        }
    }

    @Override
    public String exportMerchantData(MerchantQueryVO query, String exportFormat) {
        try {
            return merchantMapper.exportMerchantData(query, exportFormat);
        } catch (Exception e) {
            log.error("导出商户数据失败: {}", e.getMessage(), e);
            throw new RuntimeException("导出商户数据失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importMerchantData(String importData, Long importedBy) {
        try {
            return merchantMapper.importMerchantData(importData, importedBy);
        } catch (Exception e) {
            log.error("导入商户数据失败: {}", e.getMessage(), e);
            throw new RuntimeException("导入商户数据失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchProcessMerchants(List<Long> merchantIds, String processType, Long processedBy) {
        try {
            return merchantMapper.batchProcessMerchants(merchantIds, processType, processedBy) > 0;
        } catch (Exception e) {
            log.error("批量处理商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("批量处理商户失败", e);
        }
    }

    @Override
    public String getMerchantRecommendations(Long merchantId) {
        try {
            return merchantMapper.getMerchantRecommendations(merchantId);
        } catch (Exception e) {
            log.error("获取商户推荐失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取商户推荐失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean recordMerchantEvent(Long merchantId, String eventType, String eventDescription, Long recordedBy) {
        try {
            return merchantMapper.recordMerchantEvent(merchantId, eventType, eventDescription, recordedBy) > 0;
        } catch (Exception e) {
            log.error("记录商户事件失败: {}", e.getMessage(), e);
            throw new RuntimeException("记录商户事件失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMerchantRating(Long merchantId, BigDecimal rating, String feedback, Long ratedBy) {
        try {
            return merchantMapper.updateMerchantRating(merchantId, rating, feedback, ratedBy) > 0;
        } catch (Exception e) {
            log.error("更新商户评分失败: {}", e.getMessage(), e);
            throw new RuntimeException("更新商户评分失败", e);
        }
    }

    @Override
    public String getMerchantAlternatives(Long merchantId, Integer maxAlternatives) {
        try {
            return merchantMapper.getMerchantAlternatives(merchantId, maxAlternatives);
        } catch (Exception e) {
            log.error("获取商户替代方案失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取商户替代方案失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean optimizeMerchant(Long merchantId, String optimizationType, Long optimizedBy) {
        try {
            return merchantMapper.optimizeMerchant(merchantId, optimizationType, optimizedBy) > 0;
        } catch (Exception e) {
            log.error("优化商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("优化商户失败", e);
        }
    }

    @Override
    public String validateMerchant(Long merchantId) {
        try {
            return merchantMapper.validateMerchant(merchantId);
        } catch (Exception e) {
            log.error("验证商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("验证商户失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean archiveMerchant(Long merchantId, String archiveReason, Long archivedBy) {
        try {
            return merchantMapper.archiveMerchant(merchantId, archiveReason, archivedBy) > 0;
        } catch (Exception e) {
            log.error("归档商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("归档商户失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean restoreMerchant(Long merchantId, Long restoredBy) {
        try {
            return merchantMapper.restoreMerchant(merchantId, restoredBy) > 0;
        } catch (Exception e) {
            log.error("恢复商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("恢复商户失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cloneMerchant(Long sourceMerchantId, String newMerchantCode, Long clonedBy) {
        try {
            return merchantMapper.cloneMerchant(sourceMerchantId, newMerchantCode, clonedBy) > 0;
        } catch (Exception e) {
            log.error("克隆商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("克隆商户失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean mergeMerchants(List<Long> merchantIds, String newMerchantCode, Long mergedBy) {
        try {
            return merchantMapper.mergeMerchants(merchantIds, newMerchantCode, mergedBy) > 0;
        } catch (Exception e) {
            log.error("合并商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("合并商户失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean splitMerchant(Long merchantId, String splitConfig, Long splitBy) {
        try {
            return merchantMapper.splitMerchant(merchantId, splitConfig, splitBy) > 0;
        } catch (Exception e) {
            log.error("拆分商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("拆分商户失败", e);
        }
    }

    @Override
    public String calculateMerchantValue(Long merchantId) {
        try {
            return merchantMapper.calculateMerchantValue(merchantId);
        } catch (Exception e) {
            log.error("计算商户价值失败: {}", e.getMessage(), e);
            throw new RuntimeException("计算商户价值失败", e);
        }
    }

    @Override
    public Integer estimateMerchantGrowth(Long merchantId) {
        try {
            return merchantMapper.estimateMerchantGrowth(merchantId);
        } catch (Exception e) {
            log.error("预估商户增长失败: {}", e.getMessage(), e);
            throw new RuntimeException("预估商户增长失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMerchantStatistics(Long merchantId, Long updatedBy) {
        try {
            return merchantMapper.updateMerchantStatistics(merchantId, updatedBy) > 0;
        } catch (Exception e) {
            log.error("更新商户统计信息失败: {}", e.getMessage(), e);
            throw new RuntimeException("更新商户统计信息失败", e);
        }
    }

    @Override
    public String getMerchantHistory(Long merchantId) {
        try {
            return merchantMapper.getMerchantHistory(merchantId);
        } catch (Exception e) {
            log.error("获取商户历史失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取商户历史失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean notifyMerchantUpdate(Long merchantId, String notificationType, String message, Long notifiedBy) {
        try {
            return merchantMapper.notifyMerchantUpdate(merchantId, notificationType, message, notifiedBy) > 0;
        } catch (Exception e) {
            log.error("通知商户更新失败: {}", e.getMessage(), e);
            throw new RuntimeException("通知商户更新失败", e);
        }
    }

    @Override
    public String getMerchantMetrics(Long merchantId, String metricsType) {
        try {
            return merchantMapper.getMerchantMetrics(merchantId, metricsType);
        } catch (Exception e) {
            log.error("获取商户指标失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取商户指标失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean escalateMerchant(Long merchantId, String escalationReason, Long escalatedBy) {
        try {
            return merchantMapper.escalateMerchant(merchantId, escalationReason, escalatedBy) > 0;
        } catch (Exception e) {
            log.error("升级商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("升级商户失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deescalateMerchant(Long merchantId, String deescalationReason, Long deescalatedBy) {
        try {
            return merchantMapper.deescalateMerchant(merchantId, deescalationReason, deescalatedBy) > 0;
        } catch (Exception e) {
            log.error("降级商户失败: {}", e.getMessage(), e);
            throw new RuntimeException("降级商户失败", e);
        }
    }

}